{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "4cf274b1-fc0b-48df-a408-6e3944e6b63b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "from torchvision import transforms, datasets\n",
    "import json\n",
    "import matplotlib.pyplot as plt\n",
    "import os\n",
    "import torch.optim as optim\n",
    "# from model import resnet34, resnet101\n",
    "import torchvision.models.resnet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "42ea5e91-813a-4e0a-b076-a32c54105f31",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 模块类\n",
    "class BasicBlock(nn.Module):\n",
    "\n",
    "    expansion = 1\n",
    "\n",
    "    def __init__(self, in_channel, out_channel, stride=1, downsample=None):  # downsample对应虚线残差结构\n",
    "        super(BasicBlock, self).__init__()\n",
    "        # 特征提取，特征变换,调整通道数\n",
    "        self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,\n",
    "                               kernel_size=3, stride=stride, padding=1, bias=False)\n",
    "        self.bn1 = nn.BatchNorm2d(out_channel)  # BN处理\n",
    "        self.relu = nn.ReLU()\n",
    "               \n",
    "        # 特征提取，特征转换\n",
    "        self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,\n",
    "                               kernel_size=3, stride=1, padding=1, bias=False)\n",
    "        self.bn2 = nn.BatchNorm2d(out_channel)\n",
    "        self.downsample = downsample\n",
    "\n",
    "    def forward(self, x):\n",
    "        identity = x  # 存放捷径上的输出值\n",
    "        if self.downsample is not None:\n",
    "            identity = self.downsample(x)\n",
    "\n",
    "        out = self.conv1(x)\n",
    "        out = self.bn1(out)\n",
    "        out = self.relu(out)\n",
    "\n",
    "        out = self.conv2(out)\n",
    "        out = self.bn2(out)\n",
    "\n",
    "        out+=identity\n",
    "        out = self.relu(out)\n",
    "\n",
    "        return out\n",
    "\n",
    "class Bottleneck(nn.Module):\n",
    "\n",
    "    # 模块中最后一层卷积层卷积核的倍数\n",
    "    expansion = 4  # 每个conv的卷积和个数的倍数\n",
    "\n",
    "    def __init__(self, in_channel, out_channel, stride=1, downsample=None):\n",
    "        super(Bottleneck, self).__init__()\n",
    "\n",
    "        # 这一步的目的是什么\n",
    "        self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,\n",
    "                               kernel_size=1, stride=1, padding=1,bias=False)\n",
    "        self.bn1 = nn.BatchNorm2d(out_channel)  # BN处理\n",
    "        self.relu = nn.ReLU(inplace=True)\n",
    "\n",
    "        # 特征提取，特征转换\n",
    "        self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,\n",
    "                               kernel_size=3, stride=stride, padding=1, bias=False)\n",
    "        self.bn2 = nn.BatchNorm2d(out_channel)\n",
    "        self.relu = nn.ReLU(inplace=True)\n",
    "\n",
    "        self.conv3 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,\n",
    "                               kernel_size=1, stride=1, bias=False)\n",
    "        self.bn3 = nn.BatchNorm2d(out_channel)\n",
    "        self.relu = nn.ReLU(inplace=True)\n",
    "\n",
    "        self.downsample = downsample\n",
    "\n",
    "    def forward(self, x):\n",
    "        identity = x  # 存放捷径上的输出值\n",
    "        if self.downsample is not None:\n",
    "            identity = self.downsample(x)\n",
    "\n",
    "        out = self.conv1(x)\n",
    "        out = self.bn1(out)\n",
    "        out = self.relu(out)\n",
    "\n",
    "        out = self.conv2(out)\n",
    "        out = self.bn2(out)\n",
    "        out = self.relu(out)\n",
    "\n",
    "        out = self.conv3(out)\n",
    "        out = self.bn3(out)\n",
    "\n",
    "        out+=identity\n",
    "        out =self.relu(out)\n",
    "\n",
    "        return out\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4fbafd11-e942-4775-a5e3-2615f25f1ee4",
   "metadata": {},
   "outputs": [],
   "source": [
    "class ResNet(nn.Module):\n",
    "\n",
    "    def __init__(self, block, block_num, num_classes=1000):\n",
    "        '''\n",
    "        :param block:模块类\n",
    "        :param block_num: 一个列表，指定了每个层级（layer1,layer2,layer3,layer4）中残差快的数量中\n",
    "        :param num_classes:用于全连接层\n",
    "        :include_top:指定是否包含全连接层\n",
    "        '''\n",
    "\n",
    "        super(ResNet, self).__init__()\n",
    "\n",
    "        # 模型输入通道\n",
    "        self.in_channel = 64\n",
    "\n",
    "        # 调整通道数，特征提取，特征转换\n",
    "        self.conv1 = nn.Conv2d(3, self.in_channel, kernel_size=7, stride=2,\n",
    "                               padding=3, bias=False)  # 填充3个单位\n",
    "        self.bn1 = nn.BatchNorm2d(self.in_channel)\n",
    "        self.relu = nn.ReLU()\n",
    "        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)  # 最大池化层，减小空间维度和参数个数，防止过拟合\n",
    "\n",
    "        # 定义主要层级，每个层级由多个残差块组成\n",
    "        self.layer1 = self._make_layer(block, 64, block_num[0])\n",
    "        self.layer2 = self._make_layer(block, 128, block_num[1], stride=2)\n",
    "        self.layer3 = self._make_layer(block, 256, block_num[2], stride=2)\n",
    "        self.layer4 = self._make_layer(block, 512, block_num[3], stride=2)\n",
    "\n",
    "        self.avgpool =  nn.AdaptiveAvgPool2d((1, 1))  # output size = (1, 1)\n",
    "        self.fc = nn.Linear(512 * block.expansion, num_classes)\n",
    "\n",
    "        # 初始化函数，考虑了前向传播和反向传播时激活值的方差和梯度的方差，旨在保持信号在网络中的流动，避免梯度消失或爆炸问题\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, nn.Conv2d):\n",
    "                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n",
    "\n",
    "    def _make_layer(self, block, channel, block_num, stride=1):\n",
    "        '''\n",
    "        :param block:\n",
    "        :param channel: 当前层级的输出通道数\n",
    "        :param block_num: 当前层级中残差快的数量\n",
    "        :param stride:\n",
    "        :return:\n",
    "        '''\n",
    "\n",
    "        downsample = None\n",
    "\n",
    "        # 为什么满足这两种情况要添加残差快\n",
    "        # 如果stride不为1或者当前输入通道数与期望输出通道数不匹配就添加一个下采样\n",
    "        # 没达到预期标准或为深层次的卷积层\n",
    "        if stride != 1 or self.in_channel != channel * block.expansion:\n",
    "            downsample = nn.Sequential(nn.Conv2d(self.in_channel, channel * block.expansion, kernel_size=1, stride=stride, bias=False),\n",
    "                                       nn.BatchNorm2d(channel * block.expansion))\n",
    "\n",
    "        layers = []\n",
    "        layers.append(block(self.in_channel, channel * block.expansion, downsample=downsample, stride=stride))\n",
    "        self.in_channel = channel * block.expansion\n",
    "\n",
    "        for _ in range(1, block_num):\n",
    "            layers.append(block(self.in_channel, channel))\n",
    "            self.in_channel = channel\n",
    "\n",
    "        return nn.Sequential(*layers)  #  一个解包操作符，将layer列表（或元组等可迭代对象）中的元素解包成位置参数，然后传给nn.Sequential的构造函数。这样，nn.Sequential接受多个层作为输入\n",
    "\n",
    "    def forward(self, x):\n",
    "        # 调整通道数，特征提取，特征转换\n",
    "        x = self.conv1(x)\n",
    "        x = self.bn1(x)\n",
    "        x = self.relu(x)\n",
    "        x = self.maxpool(x)\n",
    "\n",
    "        # 主要层次\n",
    "        x = self.layer1(x)\n",
    "        x = self.layer2(x)\n",
    "        x = self.layer3(x)\n",
    "        x = self.layer4(x)\n",
    "\n",
    "        x = self.avgpool(x)\n",
    "        x = torch.flatten(x, 1)\n",
    "        x = self.fc(x)\n",
    "\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1896d42c-e4ac-41b1-9b7b-0c2fdd9153da",
   "metadata": {},
   "outputs": [],
   "source": [
    "def resnet34(num_classes=1000):\n",
    "    return ResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes)\n",
    "\n",
    "def resnet101(num_classes=1000):\n",
    "    return ResNet(BasicBlock, [3, 4, 23, 3], num_classes=num_classes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "f3ccc9aa-3a19-47c3-9b8e-3b8a03ea86ca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cpu\n"
     ]
    }
   ],
   "source": [
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "print(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "a326c515-5498-4f53-8eb6-5e299d6fdcc7",
   "metadata": {},
   "outputs": [],
   "source": [
    "data_transform = {\n",
    "    \"train\":transforms.Compose([# transforms.RandomResizedCrop(224),\n",
    "                               # transforms.RandomHorrizontalFlip(),\n",
    "                                transforms.Resize((224, 224)),\n",
    "                               transforms.ToTensor(),\n",
    "                               transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]),  # 来自网格参数\n",
    "    \"val\":transforms.Compose([# transforms.Resize(256),  # 将最小边长缩放到256\n",
    "                               # transforms.CenterCrop(224),\n",
    "                                transforms.Resize((224, 224)),\n",
    "                               transforms.ToTensor(),\n",
    "                               transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]),  # 来自网格参数\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ea3a853b-b62a-4759-af14-e2cc7ffb0746",
   "metadata": {},
   "outputs": [],
   "source": [
    "img_path = \"D:\\\\APP_Detection\\\\image_data\\\\dex_image\\\\\"\n",
    "\n",
    "train_dataset = datasets.ImageFolder(root=img_path + \"dex_train_image\", transform=data_transform[\"train\"])\n",
    "train_num = len(train_dataset)\n",
    "\n",
    "# 转换类别索引为类别名称字典\n",
    "class_to_idx = train_dataset.class_to_idx\n",
    "idx_to_class = dict((val, key) for key, val in class_to_idx.items())\n",
    "\n",
    "# # 将索引写入json文件\n",
    "# json_str = json.dumps(idx_to_class, indent=4)\n",
    "# with open('class_indices.json', 'w') as json_file:\n",
    "#     json_file.write(json_str)\n",
    "\n",
    "batch_size = 2\n",
    "train_loader = torch.utils.data.DataLoader(train_dataset,\n",
    "                                           batch_size=batch_size, shuffle=True,\n",
    "                                           num_workers=0)\n",
    "\n",
    "# 验证集\n",
    "validate_dataset = datasets.ImageFolder(root=img_path + \"dex_train_image\",\n",
    "                                        transform=data_transform[\"val\"])\n",
    "val_num = len(validate_dataset)\n",
    "validate_loader = torch.utils.data.DataLoader(validate_dataset,\n",
    "                                              batch_size=batch_size, shuffle=False,\n",
    "                                              num_workers=0)\n",
    "net = resnet101(num_classes=6)\n",
    "net.to(device)\n",
    "\n",
    "loss_function = nn.CrossEntropyLoss()  # 用于多分类问题的损失函数\n",
    "optimizer = optim.Adam(net.parameters(), lr=0.004) # 0.001到0.005之间，随着训练轮数的增加，‌学习率逐渐减缓"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "085f6ae3-65ca-4871-8c67-6a129a330db3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'torch.Tensor'>\n",
      "train loss:  0 %[->.................................................]1.5524<class 'torch.Tensor'>\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[8], line 12\u001b[0m\n\u001b[0;32m     10\u001b[0m \u001b[38;5;28mtype\u001b[39m(labels)\n\u001b[0;32m     11\u001b[0m optimizer\u001b[38;5;241m.\u001b[39mzero_grad()\n\u001b[1;32m---> 12\u001b[0m logits \u001b[38;5;241m=\u001b[39m net(images\u001b[38;5;241m.\u001b[39mto(device))\n\u001b[0;32m     13\u001b[0m loss \u001b[38;5;241m=\u001b[39m loss_function(logits, labels\u001b[38;5;241m.\u001b[39mto(device))\n\u001b[0;32m     14\u001b[0m loss\u001b[38;5;241m.\u001b[39mbackward()\n",
      "File \u001b[1;32mD:\\anaconda\\envs\\AppDeScams\\Lib\\site-packages\\torch\\nn\\modules\\module.py:1532\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m   1530\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)  \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[0;32m   1531\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m-> 1532\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32mD:\\anaconda\\envs\\AppDeScams\\Lib\\site-packages\\torch\\nn\\modules\\module.py:1541\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m   1536\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[0;32m   1537\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[0;32m   1538\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[0;32m   1539\u001b[0m         \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[0;32m   1540\u001b[0m         \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[1;32m-> 1541\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m forward_call(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m   1543\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m   1544\u001b[0m     result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n",
      "Cell \u001b[1;32mIn[3], line 75\u001b[0m, in \u001b[0;36mResNet.forward\u001b[1;34m(self, x)\u001b[0m\n\u001b[0;32m     73\u001b[0m x \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlayer1(x)\n\u001b[0;32m     74\u001b[0m x \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlayer2(x)\n\u001b[1;32m---> 75\u001b[0m x \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlayer3(x)\n\u001b[0;32m     76\u001b[0m x \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlayer4(x)\n\u001b[0;32m     78\u001b[0m x \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mavgpool(x)\n",
      "File \u001b[1;32mD:\\anaconda\\envs\\AppDeScams\\Lib\\site-packages\\torch\\nn\\modules\\module.py:1532\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m   1530\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)  \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[0;32m   1531\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m-> 1532\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32mD:\\anaconda\\envs\\AppDeScams\\Lib\\site-packages\\torch\\nn\\modules\\module.py:1541\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m   1536\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[0;32m   1537\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[0;32m   1538\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[0;32m   1539\u001b[0m         \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[0;32m   1540\u001b[0m         \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[1;32m-> 1541\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m forward_call(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m   1543\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m   1544\u001b[0m     result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n",
      "File \u001b[1;32mD:\\anaconda\\envs\\AppDeScams\\Lib\\site-packages\\torch\\nn\\modules\\container.py:217\u001b[0m, in \u001b[0;36mSequential.forward\u001b[1;34m(self, input)\u001b[0m\n\u001b[0;32m    215\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mforward\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;28minput\u001b[39m):\n\u001b[0;32m    216\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m module \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m:\n\u001b[1;32m--> 217\u001b[0m         \u001b[38;5;28minput\u001b[39m \u001b[38;5;241m=\u001b[39m module(\u001b[38;5;28minput\u001b[39m)\n\u001b[0;32m    218\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28minput\u001b[39m\n",
      "File \u001b[1;32mD:\\anaconda\\envs\\AppDeScams\\Lib\\site-packages\\torch\\nn\\modules\\module.py:1532\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m   1530\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)  \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[0;32m   1531\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m-> 1532\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32mD:\\anaconda\\envs\\AppDeScams\\Lib\\site-packages\\torch\\nn\\modules\\module.py:1541\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m   1536\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[0;32m   1537\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[0;32m   1538\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[0;32m   1539\u001b[0m         \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[0;32m   1540\u001b[0m         \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[1;32m-> 1541\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m forward_call(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m   1543\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m   1544\u001b[0m     result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n",
      "Cell \u001b[1;32mIn[2], line 26\u001b[0m, in \u001b[0;36mBasicBlock.forward\u001b[1;34m(self, x)\u001b[0m\n\u001b[0;32m     23\u001b[0m     identity \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdownsample(x)\n\u001b[0;32m     25\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconv1(x)\n\u001b[1;32m---> 26\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbn1(out)\n\u001b[0;32m     27\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrelu(out)\n\u001b[0;32m     29\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconv2(out)\n",
      "File \u001b[1;32mD:\\anaconda\\envs\\AppDeScams\\Lib\\site-packages\\torch\\nn\\modules\\module.py:1532\u001b[0m, in \u001b[0;36mModule._wrapped_call_impl\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m   1530\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compiled_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)  \u001b[38;5;66;03m# type: ignore[misc]\u001b[39;00m\n\u001b[0;32m   1531\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m-> 1532\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call_impl(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32mD:\\anaconda\\envs\\AppDeScams\\Lib\\site-packages\\torch\\nn\\modules\\module.py:1541\u001b[0m, in \u001b[0;36mModule._call_impl\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m   1536\u001b[0m \u001b[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001b[39;00m\n\u001b[0;32m   1537\u001b[0m \u001b[38;5;66;03m# this function, and just call forward.\u001b[39;00m\n\u001b[0;32m   1538\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_forward_pre_hooks\n\u001b[0;32m   1539\u001b[0m         \u001b[38;5;129;01mor\u001b[39;00m _global_backward_pre_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_backward_hooks\n\u001b[0;32m   1540\u001b[0m         \u001b[38;5;129;01mor\u001b[39;00m _global_forward_hooks \u001b[38;5;129;01mor\u001b[39;00m _global_forward_pre_hooks):\n\u001b[1;32m-> 1541\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m forward_call(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m   1543\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m   1544\u001b[0m     result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n",
      "File \u001b[1;32mD:\\anaconda\\envs\\AppDeScams\\Lib\\site-packages\\torch\\nn\\modules\\batchnorm.py:155\u001b[0m, in \u001b[0;36m_BatchNorm.forward\u001b[1;34m(self, input)\u001b[0m\n\u001b[0;32m    152\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtraining \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtrack_running_stats:\n\u001b[0;32m    153\u001b[0m     \u001b[38;5;66;03m# TODO: if statement only here to tell the jit to skip emitting this when it is None\u001b[39;00m\n\u001b[0;32m    154\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnum_batches_tracked \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:  \u001b[38;5;66;03m# type: ignore[has-type]\u001b[39;00m\n\u001b[1;32m--> 155\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnum_batches_tracked\u001b[38;5;241m.\u001b[39madd_(\u001b[38;5;241m1\u001b[39m)  \u001b[38;5;66;03m# type: ignore[has-type]\u001b[39;00m\n\u001b[0;32m    156\u001b[0m         \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmomentum \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:  \u001b[38;5;66;03m# use cumulative moving average\u001b[39;00m\n\u001b[0;32m    157\u001b[0m             exponential_average_factor \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1.0\u001b[39m \u001b[38;5;241m/\u001b[39m \u001b[38;5;28mfloat\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnum_batches_tracked)\n",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "best_acc = 0.0  # 用于记录模型在验证集上的最佳准确率\n",
    "save_path = \"D:\\\\resnet\\\\resnet34_best\"  # 保存模型权重的路径\n",
    "for epoch in range(3):  # 每个epoch代表整个训练集被遍历一次\n",
    "    # train\n",
    "    net.train()\n",
    "    running_loss = 0.0\n",
    "    for step, data in enumerate(train_loader, start=0):\n",
    "        images, labels = data\n",
    "        print(type(images))\n",
    "        type(labels)\n",
    "        optimizer.zero_grad()\n",
    "        logits = net(images.to(device))\n",
    "        loss = loss_function(logits, labels.to(device))\n",
    "        loss.backward()\n",
    "        optimizer.step()  # 更新模型参数\n",
    "\n",
    "        # print statistics\n",
    "        running_loss += loss.item()\n",
    "        # print train process\n",
    "        rate = (step + 1) / len(train_loader)\n",
    "        a = \"*\" * int(rate * 50)\n",
    "        b = \".\" * int((1 - rate) * 50)\n",
    "        print(\"\\rtrain loss: {:^3.0f}%[{}->{}]{:.4f}\".format(int(rate * 100), a, b, loss), end=\"\")\n",
    "    print()\n",
    "\n",
    "    # validate\n",
    "    net.eval()  # 将模型设置为评估模式\n",
    "    acc = 0.0  # 初始化准确率累加器\n",
    "    with torch.no_grad():\n",
    "        for val_step, val_data in enumerate(validate_loader, start=0):\n",
    "            val_images, val_labels = val_data\n",
    "            outputs = net(val_images.to(device))  # eval model only have last output layer\n",
    "            # loss = loss_function(outputs, test_labels)\n",
    "            predict_y = torch.max(outputs, dim=1)[1]\n",
    "            acc += (predict_y == val_labels.to(device)).sum().item()\n",
    "            test_progress_rate = (val_step + 1) / len(validate_loader)\n",
    "            c = \"*\" * int(test_progress_rate * 50)\n",
    "            d = \".\" * int((1 - test_progress_rate) * 50)\n",
    "            print(\"\\rtest progress: {:^3.0f}%[{}->{}]\".format(int(test_progress_rate * 100), c, d), end=\"\")\n",
    "    print()\n",
    "\n",
    "        val_accurate = acc / val_num\n",
    "        if val_accurate > best_acc:\n",
    "            best_acc = val_accurate\n",
    "            torch.save(net.state_dict(), save_path)\n",
    "        print('[epoch %d] train_loss: %.3f  test_accuracy: %.3f' %\n",
    "              (epoch + 1, running_loss / step, val_accurate*100))\n",
    "\n",
    "print('Finished Training')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "301d44fe-252f-488b-8753-d3adb9eab78e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ec5b284f-3195-4663-bf3c-5540777f0469",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "AppDeScams",
   "language": "python",
   "name": "appdescams"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
